home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / Generic List Library / generic_list.docs < prev    next >
Encoding:
Text File  |  1994-08-21  |  24.5 KB  |  623 lines  |  [TEXT/R*ch]

  1.    *************************************************************************
  2.    *************************************************************************
  3.    **                                                                     **
  4.    **                        Generic List Library                         **
  5.    **                                                                     **
  6.    **                          by Keith Pomakis                           **
  7.    **                     kppomaki@jeeves.uwaterloo.ca                    **
  8.    **                                                                     **
  9.    **                            Spring, 1994                             **
  10.    **                                                                     **
  11.    *************************************************************************
  12.    *************************************************************************
  13.  
  14.                            ****  Documentation  ****
  15.  
  16.  
  17. ****************************************************************************
  18. PURPOSE AND HISTORY
  19. ****************************************************************************
  20.  
  21. The basic data structures of lists, stacks and queues are fundamental to
  22. programming at almost every level.  However, because of the nature of the C
  23. programming language, it is difficult to program a set of generic list
  24. functions without sacrificing simplicity.  Therefore, C programmers often
  25. find themselves programming specialized list functions over and over again.
  26. This is not only a large waste of effort, but can also be the source of many
  27. errors since each individual implementation is often tested only
  28. haphazardly.
  29.  
  30. After countless assignments and projects (both academic and personal) in
  31. which I found myself constantly rewriting the same list manipulation
  32. functions in slightly different contexts, I figured it was about time to
  33. take the effort and program an efficient, flexible, and easy-to-use library
  34. of generic list functions.  And that is exactly what I did!
  35.  
  36. It is my hope that, in distributing this library, others will be able to use
  37. what I've put together to increase their own programming productivity.
  38.  
  39.  
  40. ****************************************************************************
  41. DISCLAIMER
  42. ****************************************************************************
  43.  
  44. I am releasing this library to the public domain.  Therefore, people can use
  45. it, copy it, distribute it, modify it, and do whatever they want with it.
  46.  
  47. Although this library has been well thought out, tested, and used in real
  48. applications, it is not guaranteed to be bug-free.  Therefore, I am not
  49. responsible for anything that happens, either directly or indirectly, due to
  50. the usage of this library.
  51.  
  52. If you modify or add to this library in any way, I'd appreciate it if you
  53. dropped me a line (or Internet packet, whatever) telling me what you did.
  54. I'm always interested in potential improvements to my work!
  55.  
  56. Also, if you find any bugs (gasp!) or have any questions or comments about
  57. the library, you can contact me as well.  My e-mail address is
  58. "kppomaki@jeeves.uwaterloo.ca".  I'd be interested in hearing what you
  59. think!
  60.  
  61. Oh, one other thing... I've put a lot of work into this library, so I'd
  62. appreciate it if you kept my name attached to it when distributing or
  63. modifying it.
  64.  
  65.  
  66. ****************************************************************************
  67. REQUIREMENTS
  68. ****************************************************************************
  69.  
  70. The only requirements for the usage of this library are an ANSI C compiler,
  71. a machine to run it on, and a project that is in need of generic list
  72. functions!  This library has been tested with gcc on a Sun 4 and with Think
  73. C on a Macintosh.  The code is ANSI-compliant, and should present no problem
  74. with any other setup.
  75.  
  76.  
  77. ****************************************************************************
  78. PHILOSOPHY
  79. ****************************************************************************
  80.  
  81. My goal when designing this library was to make it as flexible and complete
  82. as possible, while still keeping it efficient and easy to use.  I have seen
  83. and have tried to use other generic list libraries (and yes, I realize they
  84. are numerous), but often they have failed me on one or more of the above
  85. points.  I also realize that such a library would be a trivial piece of work
  86. in C++.  However, as much of a proponent of the object-oriented paradigm as
  87. I am, I tend to dislike C++ because of the hideous syntactic nightmares I
  88. get when tackling the language.  Therefore, I have decided to write the
  89. library in C.
  90.  
  91. A set of basic generic doubly-linked list functions were designed and
  92. programmed first (along with a suitable efficient data structure), and then
  93. some higher-level functions were added to increase ease of use.  The
  94. functionality of stacks, queues and sorted lists were then added.  In
  95. actuality, these functions (with the exception of one of the sorted-list
  96. functions) are nothing more than aliases for the appropriate generic list
  97. operations.  This aliasing is behind the scenes, however, and the user of
  98. this library may treat the operation of lists, stacks and queues in this
  99. library as completely separate functionality.
  100.  
  101. In order to make the library completely generic, it was designed to
  102. manipulate pointers of type void *.  Therefore, it is assumed that the
  103. programmer is statically or dynamically creating the objects of interest,
  104. and using the generic list functions to manipulate them.  It is up to the
  105. programmer to handle the allocation and deallocation of the memory for the
  106. objects themselves.
  107.  
  108. A pointer to the same object may be stored in a list multiple times.  The
  109. only restriction imposed is that a NULL pointer may not be stored.
  110.  
  111.  
  112. ****************************************************************************
  113. USAGE
  114. ****************************************************************************
  115.  
  116. The use of this library is simple and straight-forward.  In every source
  117. file that requires the use of generic list functions, the line:
  118.  
  119. #include "generic_list.h"
  120.  
  121. must be included at the top of the file.  For those who hand-craft their own
  122. makefiles, "generic_list.h" should become a prerequisite for each of these
  123. files, as well as for "generic_list.c" itself.
  124.  
  125. The library defines three data types:
  126.  
  127.     Generic_list
  128.     Generic_stack
  129.     Generic_queue
  130.  
  131. The usage of these functions is best illustrated with an example:
  132.  
  133. foo() {
  134.     Generic_stack stack;
  135.     My_object *obj;
  136.  
  137.     initialize_stack(&stack);
  138.  
  139.     obj = new_object();
  140.     push(stack, obj);
  141.     ...
  142.     obj = pop(stack);
  143.     free(obj);
  144.     ...
  145.     destroy_stack(&stack);
  146. }
  147.  
  148. Each list must be initialized before use and should be destroyed after it is
  149. no longer needed.  The programmer must handle the allocation and
  150. deallocation of the memory for the objects being stored.  Explicit memory
  151. management for the lists is not necessary.
  152.  
  153.  
  154. ****************************************************************************
  155. LIST OF FUNCTIONS
  156. ****************************************************************************
  157.  
  158. The following are the headers of the functions provided in the generic list
  159. library.  They are described in more detail later.
  160.  
  161. Generic Lists
  162. -------------
  163.  
  164. void initialize_list(Generic_list *list);
  165. void destroy_list(Generic_list *list);
  166. void add_to_beginning(Generic_list list, void *pointer);
  167. void add_to_end(Generic_list list, void *pointer);
  168. void add_to_list(Generic_list list, void *pointer);
  169. void *remove_from_beginning(Generic_list list);
  170. void *remove_from_end(Generic_list list);
  171. void *remove_from_list(Generic_list list, void *pointer);
  172. void *peek_at_beginning(Generic_list list);
  173. void *peek_at_end(Generic_list list);
  174.  
  175. void *first_in_list(Generic_list list);
  176. void *next_in_list(Generic_list list);
  177. void *current_in_list(Generic_list list);
  178. void *remove_current(Generic_list list);
  179. void *previous_in_list(Generic_list list);
  180. void *last_in_list(Generic_list list);
  181. void reset_to_beginning(Generic_list list);
  182. void reset_to_end(Generic_list list);
  183.  
  184. int num_of_objects(const Generic_list list);
  185. int is_empty(const Generic_list list);
  186. int is_in_list(const Generic_list list, const void *pointer);
  187. Generic_list copy_list(Generic_list list);
  188.  
  189. void perform_on_list
  190.      (Generic_list list, void (*fn)(void *pointer, void *args), void *args);
  191. void *first_that
  192.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  193.                          const void *args);
  194. void *next_that
  195.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  196.                          const void *args);
  197. void *previous_that
  198.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  199.                          const void *args);
  200. void *last_that
  201.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  202.                          const void *args);
  203. Generic_list all_such_that
  204.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  205.                          const void *args);
  206. void remove_all_such_that
  207.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  208.                          const void *args);
  209.  
  210.  
  211. Generic Sorted Lists
  212. --------------------
  213.  
  214. void initialize_sorted_list(Generic_list *list, int (*lt)(void *a, void *b));
  215.  
  216. ...and all Generic_list functions except:
  217.  
  218. void add_to_beginning(Generic_list list, void *pointer);
  219. void add_to_end(Generic_list list, void *pointer);
  220. void *remove_from_beginning(Generic_list list);
  221. void *remove_from_end(Generic_list list);
  222.  
  223.  
  224. Generic Stacks
  225. --------------
  226.  
  227. void initialize_stack(Generic_stack *stack);
  228. void destroy_stack(Generic_stack *stack);
  229. void push(Generic_stack stack, void *pointer);
  230. void *pop(Generic_stack stack);
  231. void pop_all(Generic_stack stack);
  232. void *peek_at_top(Generic_stack stack);
  233. Generic_stack copy_stack(Generic_stack stack);
  234. int is_empty(const Generic_stack stack);
  235.  
  236.  
  237. Generic Queues
  238. --------------
  239.  
  240. void initialize_queue(Generic_queue *queue);
  241. void destroy_queue(Generic_queue *queue);
  242. void enqueue(Generic_queue queue, void *pointer);
  243. void *dequeue(Generic_queue queue);
  244. void dequeue_all(Generic_queue queue);
  245. void *peek_at_head(Generic_queue queue);
  246. void *peek_at_tail(Generic_queue queue);
  247. Generic_queue copy_queue(Generic_queue queue);
  248. int is_empty(const Generic_queue queue);
  249.  
  250.  
  251. ****************************************************************************
  252. DETAILED DESCRIPTION OF FUNCTIONS
  253. ****************************************************************************
  254.  
  255. Generic Lists
  256. -------------
  257.  
  258. void initialize_list(Generic_list *list);
  259.  
  260.     Every list must be initialized before it is used, unless it is the
  261.     destination of a copy.  The only time it is valid to re-initialize a
  262.     list is after it has been destroyed.
  263.  
  264. void destroy_list(Generic_list *list);
  265.  
  266.     When a list is no longer needed, it should be destroyed.  This process
  267.     will automatically remove all remaining objects from the list.  However,
  268.     the memory for these objects will not be reclaimed, so if the objects
  269.     have no other references, care should be taken to purge the list and
  270.     free all objects before destroying the list.
  271.  
  272.     It is an error to destroy a list more than once (unless it has been
  273.     re-initialized in the meantime).
  274.  
  275. void add_to_beginning(Generic_list list, void *pointer);
  276.  
  277.     This function will add the specified object to the beginning of the
  278.     list.  The pointer must not be NULL.
  279.  
  280. void add_to_end(Generic_list list, void *pointer);
  281.  
  282.     This function will add the specified object to the end of the
  283.     list.  The pointer must not be NULL.
  284.  
  285. void add_to_list(Generic_list list, void *pointer);
  286.  
  287.     This function will add the specified object to the list.  The pointer
  288.     must not be NULL.
  289.  
  290. void *remove_from_beginning(Generic_list list);
  291.  
  292.     This function will remove the first object from the beginning of the
  293.     list and return it.  If the list is empty, NULL is returned.
  294.  
  295. void *remove_from_end(Generic_list list);
  296.  
  297.     This function will remove the last object from the end of the list and
  298.     return it.  If the list is empty, NULL is returned.
  299.  
  300. void *remove_from_list(Generic_list list, void *pointer);
  301.  
  302.     This function will remove the specified object from the list and return
  303.     it.  If the specified object does not exist in the list, NULL is
  304.     returned.  If the specified object exists in the list more than once,
  305.     only the last reference to it is removed.
  306.  
  307. void remove_all(Generic_list list);
  308.  
  309.     This function will remove all objects from the list.  Note that the
  310.     memory for these objects will not be reclaimed, so if the objects have
  311.     no other references, they should be removed one at a time, freeing them
  312.     when necessary.
  313.  
  314. void *peek_at_beginning(Generic_list list);
  315.  
  316.     This function will return the first object in the list.  If the list is
  317.     empty, NULL is returned.
  318.  
  319. void *peek_at_end(Generic_list list);
  320.  
  321.     This function will return the last object in the list.  If the list is
  322.     empty, NULL is returned.
  323.  
  324. void *first_in_list(Generic_list list);
  325.  
  326.     This function will return the first object in the list and mark it as
  327.     the current object.  If the list is empty, NULL is returned.
  328.  
  329. void *next_in_list(Generic_list list);
  330.  
  331.     This function will return the next object in the list and mark it as
  332.     the current object.  If the end of the list is reached, or if the list
  333.     is empty, NULL is returned.
  334.  
  335. void *current_in_list(Generic_list list);
  336.  
  337.     This function will return the object in the list that is considered
  338.     the current object (as defined by the surrounding functions).  If the
  339.     current object has just been removed, if current points to the
  340.     beginning or end of the list, or if the list is empty, NULL is
  341.     returned.
  342.  
  343. void *remove_current(Generic_list list);
  344.  
  345.     This function will remove the current object from the list and return
  346.     it.  If the current object has already been removed, if current points
  347.     to the beginning or end of the list, or if the list is empty, NULL is
  348.     returned.
  349.  
  350. void *previous_in_list(Generic_list list);
  351.  
  352.     This function will return the previous object in the list and mark it
  353.     as the current object.  If the beginning of the list is reached, or if
  354.     the list is empty, NULL is returned.
  355.  
  356. void *last_in_list(Generic_list list);
  357.  
  358.     This function will return the last object in the list and mark it as
  359.     the current object.  If the list is empty, NULL is returned.
  360.  
  361. void reset_to_beginning(Generic_list list);
  362.  
  363.     This function will reset the list to the beginning.  Therefore, current
  364.     points to the beginning of the list, and the next object in the list is
  365.     the first object.
  366.  
  367. void reset_to_end(Generic_list list);
  368.  
  369.     This function will reset the list to the end.  Therefore, current
  370.     points to the end of the list, and the previous object in the list is
  371.     the last object.
  372.  
  373. int num_of_objects(const Generic_list list);
  374.  
  375.     This function will return the number of objects in the list.
  376.  
  377. int is_empty(const Generic_list list);
  378.  
  379.     This function will return TRUE (1) if the list is empty, and FALSE (0)
  380.     otherwise.
  381.  
  382. int is_in_list(const Generic_list list, const void *pointer);
  383.  
  384.     This function will return TRUE (1) if the specified object is a member
  385.     of the list, and FALSE (0) otherwise.  Note that this only compares
  386.     object pointers.  If an identical object is a member of the list, but
  387.     occupies a different location in memory, this function will return
  388.     FALSE.
  389.  
  390. Generic_list copy_list(Generic_list list);
  391.  
  392.     This function will return a copy of the list.  The objects themselves
  393.     are not copied; only new references to them are made.  The new list
  394.     loses its concept of the current object.  The destination of this copy
  395.     need not be initialized.  However, care must be taken to destroy the
  396.     copy when it is no longer needed.
  397.  
  398. void perform_on_list
  399.      (Generic_list list, void (*fn)(void *pointer, void *args), void *args);
  400.  
  401.     This function will perform the specified function on each object in the
  402.     list.  Any optional arguments required can be passed through args.
  403.  
  404. void *first_that
  405.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  406.                          const void *args);
  407.  
  408.      This function will find and return the first object in the list which
  409.      causes the specified function to return a TRUE (non-zero) value.  Any
  410.      optional arguments required can be passed through args.  The found
  411.      object is then marked as the current object.  If no objects in the list
  412.      meet the criteria of the specified function, NULL is returned.
  413.  
  414. void *next_that
  415.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  416.                          const void *args);
  417.  
  418.      This function will find and return the next object in the list which
  419.      causes the specified function to return a TRUE (non-zero) value.  Any
  420.      optional arguments required can be passed through args.  The found
  421.      object is then marked as the current object.  If there are no objects
  422.      left in the list that meet the criteria of the specified function,
  423.      NULL is returned.
  424.  
  425. void *previous_that
  426.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  427.                          const void *args);
  428.  
  429.      This function will find and return the previous object in the list
  430.      which causes the specified function to return a TRUE (non-zero) value.
  431.      Any optional arguments required can be passed through args.  The found
  432.      object is then marked as the current object.  If there are no objects
  433.      left in the list that meet the criteria of the specified function,
  434.      NULL is returned.
  435.  
  436. void *last_that
  437.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  438.                          const void *args);
  439.  
  440.      This function will find and return the last object in the list which
  441.      causes the specified function to return a TRUE (non-zero) value.  Any
  442.      optional arguments required can be passed through args.  The found
  443.      object is then marked as the current object.  If no objects in the
  444.      list meet the criteria of the specified function, NULL is returned.
  445.  
  446. Generic_list all_such_that
  447.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  448.                          const void *args);
  449.  
  450.     This function will return a new list containing all of the objects in
  451.     the specified list which cause the specified function to return a TRUE
  452.     (non-zero) value.  Any optional arguments required can be passed
  453.     through args. The objects themselves are not copied; only new
  454.     references to them are made.  Care must be taken to destroy this new
  455.     list when it is no longer needed.
  456.  
  457. void remove_all_such_that
  458.      (Generic_list list, int (*fn)(const void *pointer, const void *args),
  459.                          const void *args);
  460.  
  461.     This function will remove all objects in the list which cause the
  462.     specified function to return a TRUE (non-zero) value.  Any optional
  463.     arguments required can be passed through args.  Note that the memory
  464.     for these objects will not be reclaimed, so if the objects have
  465.     no other references, it is best to avoid this function and remove the
  466.     objects one by one, freeing them when necessary.
  467.  
  468.  
  469. Generic Sorted Lists
  470. --------------------
  471.  
  472. void initialize_sorted_list(Generic_list *list, int (*lt)(void *a, void *b));
  473.  
  474.     This function initializes a sorted list.  A less-than function must be
  475.     specified which accepts two pointers, a and b, and returns TRUE
  476.     (non-zero) if a is less than b, FALSE otherwise.
  477.  
  478.     Once a list is initialized in this way, all of the generic list
  479.     functions described above can be used, except for:
  480.  
  481.         void add_to_beginning(Generic_list list, void *pointer);
  482.         void add_to_end(Generic_list list, void *pointer);
  483.         void *remove_from_beginning(Generic_list list);
  484.         void *remove_from_end(Generic_list list);
  485.  
  486.     In particular, the function add_to_list() should be used to add
  487.     objects to the sorted list.  This will insure that the list will
  488.     remain sorted by the criteria specified by the less-than function.
  489.  
  490.     The only time it is valid to re-initialize a list is after it has been
  491.     destroyed.
  492.  
  493.  
  494. Generic Stacks
  495. --------------
  496.  
  497. void initialize_stack(Generic_stack *stack);
  498.  
  499.     Every stack must be initialized before it is used, unless it is the
  500.     destination of a copy.  The only time it is valid to re-initialize a
  501.     stack is after it has been destroyed.
  502.  
  503. void destroy_stack(Generic_stack *stack);
  504.  
  505.     When a stack is no longer needed, it should be destroyed.  This process
  506.     will automatically remove all remaining objects from the stack.
  507.     However, the memory for these objects will not be reclaimed, so if the
  508.     objects have no other references, care should be taken to purge the
  509.     stack and free all objects before destroying the stack.
  510.  
  511.     It is an error to destroy a stack more than once (unless it has been
  512.     re-initialized in the meantime).
  513.  
  514. void push(Generic_stack stack, void *pointer);
  515.  
  516.     This function will push the specified object onto the stack.  The
  517.     pointer must not be NULL.
  518.  
  519. void *pop(Generic_stack stack);
  520.  
  521.     This function will pop the first object from the top of the stack and
  522.     return it.  If the stack is empty, NULL is returned.
  523.  
  524. void pop_all(Generic_stack stack);
  525.  
  526.     This function will pop all objects from the stack.  Note that the
  527.     memory for these objects will not be reclaimed, so if the objects have
  528.     no other references, they should be popped one at a time, freeing them
  529.     when necessary.
  530.  
  531. void *peek_at_top(Generic_stack stack);
  532.  
  533.     This function will return the object on the top of the stack.  If the
  534.     stack is empty, NULL is returned.
  535.  
  536. Generic_stack copy_stack(Generic_stack stack);
  537.  
  538.     This function will return a copy of the stack.  The objects themselves
  539.     are not copied; only new references to them are made.  The destination
  540.     of this copy need not be initialized.  However, care must be taken to
  541.     destroy this copy when it is no longer needed.
  542.  
  543. int is_empty(const Generic_stack stack);
  544.  
  545.     This function will return TRUE (1) if the stack is empty, and FALSE (0)
  546.     otherwise.
  547.  
  548.  
  549. Generic Queues
  550. --------------
  551.  
  552. void initialize_queue(Generic_queue *queue);
  553.  
  554.     Every queue must be initialized before it is used, unless it is the
  555.     destination of a copy.  The only time it is valid to re-initialize a
  556.     queue is after it has been destroyed.
  557.  
  558. void destroy_queue(Generic_queue *queue);
  559.  
  560.     When a queue is no longer needed, it should be destroyed.  This process
  561.     will automatically remove all remaining objects from the queue.
  562.     However, the memory for these objects will not be reclaimed, so if the
  563.     objects have no other references, care should be taken to purge the
  564.     queue and free all objects before destroying the queue.
  565.  
  566.     It is an error to destroy a queue more than once (unless it has been
  567.     re-initialized in the meantime).
  568.  
  569. void enqueue(Generic_queue queue, void *pointer);
  570.  
  571.     This function will add the specified object to the tail of the queue.
  572.     The pointer must not be NULL.
  573.  
  574. void *dequeue(Generic_queue queue);
  575.  
  576.     This function will remove the first object from the head of the queue
  577.     and return it.  If the queue is empty, NULL is returned.
  578.  
  579. void dequeue_all(Generic_queue queue);
  580.  
  581.     This function will remove all objects from the queue.  Note that the
  582.     memory for these objects will not be reclaimed, so if the objects have
  583.     no other references, they should be dequeued one at a time, freeing
  584.     them when necessary.
  585.  
  586. void *peek_at_head(Generic_queue queue);
  587.  
  588.     This function will return the object at the head of the queue.  If the
  589.     queue is empty, NULL is returned.
  590.  
  591. void *peek_at_tail(Generic_queue queue);
  592.  
  593.     This function will return the object at the tail of the queue.  If the
  594.     queue is empty, NULL is returned.
  595.  
  596. Generic_queue copy_queue(Generic_queue queue);
  597.  
  598.     This function will return a copy of the queue.  The objects themselves
  599.     are not copied; only new references to them are made.  The destination
  600.     of this copy need not be initialized.  However, care must be taken to
  601.     destroy this copy when it is no longer needed.
  602.  
  603. int is_empty(const Generic_queue queue);
  604.  
  605.     This function will return TRUE (1) if the queue is empty, and FALSE (0)
  606.     otherwise.
  607.  
  608.  
  609. ****************************************************************************
  610. HINTS AND RECOMMENDATIONS
  611. ****************************************************************************
  612.  
  613. Technically, any of the above functions can be used with any of the three
  614. data types.  For example, one can use perform_on_list() to perform a
  615. specified function on every object in a queue, or is_in_list() to determine
  616. whether or not a particular object is a member of a stack.  One can even
  617. pop from a queue and dequeue from a stack.  However, such usage is not
  618. recommended, as it is contrary to the logical usage of such data
  619. structures.
  620.  
  621. A priority queue can be implemented with a sorted list.
  622.  
  623.